package com.yang.imbatis.factory;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;

/**
 * @Description: jdk动态代理的调用处理器
 * @author: Yang Qiang
 * @create: 2021-10-18 21:28
 */
@Slf4j
public class YangInvocationHandler implements InvocationHandler {
	// 必要参数: 目标对象
	private Object target;

	// JDBC的参数, 来执行SQL语句的
	PreparedStatement preparedStatement = null;

	public YangInvocationHandler() {
	}

	// 构造器传入目标对象
	public YangInvocationHandler(Object target) {
		this.target = target;
	}

	/*
			参数1: 代理对象,一般不用

			参数2: 方法对象
				- 比如我们目标接口里面的findAll方法, 然后生成的代理类对象把这个方法封装为一个对象, 传进来, 让我们
				可以执行目标对象里面的原始方法, 可以得到方法的一些参数, 得到方法的注解, 然后对参数进行判断, 然后根据
				判断来继续做什么事情, 比如我们得到方法上的注解是@Select的话, 就调用JDBC的查询方法然后传入注解的参数
				也就是语句,进行查询
				- 方法对象的API可以系统的去网上学习
		 */
	@Override
	public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

//		log.debug("自定义的前置增强");
//		Object invoke = method.invoke(target);
//		return invoke;
		if (method.isAnnotationPresent(Select.class)){
			Select select = method.getAnnotation(Select.class);
			String sql = select.value()[0];
			// 执行SQL语句
			log.debug("执行SQL语句{}", sql);
		}

		// JDK不好的地方就是会代理我们的toString方法, 所以我们需要对toString方法进行从写
		// 不然的话我们调用代理对象的toString打印一个null(是名字为"null",不是对象为null)
		// 因为所有的代理对象调用方法都会走这个invoke方法, 本身invoke是没有toString方法的

		return null;
	}
}
